package wili.attrMapping._user.b1;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import wili.a.Refs;
import wili.attrMapping._user.b1.exp.AndOrExp2;
import wili.attrMapping._user.b1.exp.AndOrNode2;
import wili.attrMapping._user.b1.exp.Cpb1;
import wili.attrMapping._user.b1.exp.Valueb1;
import wili.attrMapping.core.Atts;
import wili.attrMapping.file.JsonFile;
import wili.b1.IncludesFun9;
import wili.c.Ca;
import wili.c.File9a;
import wili.c.Str9a;
import wili.json.JsonNode;

/**
 * b1 commons.
 *
 * @author weila 2022年10月8日
 */
public class B1com {
	public static void main(String[] args) {
		int opt = 1;
		File b1 = new File("C:\\bearJ\\awilly\\src\\main\\java\\wili\\attMaping\\b1");
		File a1 = new File(b1, "a1");
		if (opt == 1) {
			File[] ff = a1.listFiles(f -> f.getName().endsWith(".txt.json"));
			for (File file : ff) {
				formularTransform(file);
			}
		} else if (opt == 2) {
			moveVisibleFormular(a1, ".txt.json", ".abc", new File(b1, "a2"), ".json", ".abc");
		}
		if ("".isEmpty())
			return;
		Ca.log(quoteNum_relatesToObjType("[17,'540000006'].includes(${ObjType}))"));
	}

	static void removeSalesOrPurchaseObjType_fromNode(Atts atts, AndOrNode2 node) {
		String kind = atts.getKind();
		if (++inc == 23)
			Ca.pause();
		if (kind.equals("P")) {
			removeRegValueFromNode("'(-10000|13|14|15|16|17|23|234000031)'", node);
		} else if (kind.equals("S")) {
			removeRegValueFromNode("'(540000006|1470000113|22|18|-10001|59|20|21|19|234000032)'", node);
		} else {
			Ca.asert(false, kind);
		}
		node.removeTrueFalseNode();
	}

	static void removeRegValueFromNode(String valueReg, AndOrNode2 node) {

		Predicate<AndOrNode2> pred = new Predicate<AndOrNode2>() {

			@Override
			public boolean test(AndOrNode2 nod) {
				if (nod.sons != null)
					return false;
				if (nod.mathExp != null) {
					if (nod.mathExp instanceof Cpb1) {
						Cpb1 cp = (Cpb1) nod.mathExp;
						Refs.now();
						String[] lrs = { cp.rr.expSt, cp.ll.expSt };
						for (String value : lrs) {
							if (value.matches(valueReg)) {
								if (cp.op.matches("===?|eq"))
									nod.setMathExp(new Valueb1(false));
								else if (cp.op.matches("!==?|ne")) {
									nod.setMathExp(new Valueb1(true));
								}
							}
						}
					}
				}
				return false;
			}
		};
		node.traverse(pred);
	}

	static void moveVisibleFormular(File fromDir, String sufix1, String notSufix1, File toDir, String sufix2,
			String notSufix2) {
		Map<String, List<JsonNode>> fMap = new HashMap<>();
		File[] ff = fromDir.listFiles(f -> f.getName().endsWith(sufix1) && !f.getName().endsWith(notSufix1));
		File[] tt = toDir.listFiles(f -> f.getName().endsWith(sufix2) && !f.getName().endsWith(notSufix2));
		for (File from : ff) {
			JsonFile file = new JsonFile(from);
			file.findNodeMap_mathPath(fMap, "guid", "visible", "formula");
		}
		Map<String, List<JsonNode>> tMap = new HashMap<>();
		List<JsonFile> tos2 = Stream.of(tt).map(e -> new JsonFile(e)).collect(Collectors.toList());
		for (JsonFile file : tos2) {
			file.findNodeMap_mathPath(tMap, "guid", "visible");
		}
		for (String id : fMap.keySet()) {
			List<JsonNode> lis = fMap.get(id);
			List<JsonNode> toLis = tMap.get(id);
			if (toLis == null)
				continue;
			String fm = lis.get(0).stringValue;
			JsonNode to = toLis.get(0);
			Ca.log("\n修改前：" + to.stringValue + ", id: " + id);
			Ca.log("修改后：" + fm);
			to.setStringValue(fm);
		}
		for (JsonFile to : tos2) {
			to.saveToFile(to.file, null);
		}
	}

	public static boolean dadDad_is_content(JsonNode nd) {
		if (nd.dad != null) {
			if (nd.dad.dad != null) {
				JsonNode pp = nd.dad.dad;
				if (pp.attName.matches("actionBar|abc")) {
					return true;// 数组的每个子都不能有editable属性吗? eg. "2d661f3e-c453-4be7-aa12-130c61d0e14b".
				}
			}
		}
		return false;
	}

	/**
	 * eg. [17,'6'].includes(${ObjType}) ~> ['17','6'].includes(${ObjType})
	 * 
	 * @param fileSt
	 * @return
	 */
	public static String quoteNum_relatesToObjType(String fileSt) {
		if (Boolean.FALSE) {
			String pat = ",?'(540000006|1470000113|22|18|-10001|59|20|21|19|234000032)',?";
			fileSt = fileSt.replaceAll(pat, "");
		}
		{//找到$1的内容，把未加引号的数字加上引号
			//String st2 = Str9a.findFindReplace_all(reg, 1, st, 0, "([^'])(\\d+)([^'])", "$1'$2'$3");
			/*
			 eg. [23,3,17,'6'].includes(${ObjType})
			 找到中括号中的内容，把其中的每个数值，上引号
			 */
			String lrReg = "(\\[[^\\[\\]]+\\]).includes\\(\\$\\{ObjType\\}\\)";
			String ret = Str9a.findAndReplaceInFindResult(lrReg, 1, fileSt, 0, "(?<=[^'\\d])(\\d+)(?=[^'\\d])", "'$1'");
			//String ret = Str9a.findThenReplaceAll(reg, 0, fileSt, 0, "(?<=[^'\\w])(\\w+)(?=[^'\\w])", "'$1'");
			//eg. ${ObjType}!=23 ~>${ObjType}!='23' 
			ret = ret.replaceAll("(\\$\\{ObjType\\}\\s*(!==|===))\\s*(\\d+)", "$1'$3'");
			if (!fileSt.equals(ret))
				return ret;
			return fileSt;
		}
	}

	public static String standarlizeExpOp(String exp) {
		exp = exp.replaceAll("([\\W\\s])(eq|ne|and|or)([\\W\\s])", "$1 $2 $3").replaceAll("\\s+", " ");
		String[] ops = { " and ", " && ", " or ", " || ", " eq ", " === ", " ne ", " !== " };
		for (int i = 0; i < ops.length; i += 2) {
			exp = exp.replace(ops[i], ops[i + 1]);
		}
		exp = exp.trim();
		if (exp.startsWith("{=")) {
			exp = exp.substring(2, exp.length() - 1);
		}
		exp = Str9a.removeRedundantBracket('(', ')', exp);
		return exp;
	}

	public static void formularTransform(File file) {
		String fileSt = File9a.strOfFile(file, "");
		String reg = "(`(formula|editableFormular|formulaViewMode|formulaAddMode|formulaUpdateMode)`:\\s*)`([^`]+)`"
				.replace("`", "\"");
		String ret = Str9a.replaceRegMatchWithFun(reg, fileSt, new BiFunction<String, Matcher, String>() {
			@Override
			public String apply(String t, Matcher u) {
				String fm = u.group(3);
				if (fm.startsWith("${"))
					return u.group();
				try {
					String fm2 = B1com.formularTransform(null, fm, true);
					return u.group(1) + '"' + fm2 + '"';
				} catch (Exception e) {
					e.printStackTrace();
					return u.group(1) + '"' + "${weilai84} && " + fm + '"';
				}
			}
		});
		ret = B1com.quoteNum_relatesToObjType(ret);
		if (!ret.equals(fileSt)) {
			File9a.str2file(ret, file, -1);
			Ca.log("formularTransform: " + file.getName());
		} else {
			Ca.log("formularTransform: " + file.getName() + ", same.");
		}
	}

	public static String formularTransform(Atts oldAtts, String oldFmSt, boolean encloseByLR) {
		Ca.asert(!oldFmSt.contains("${"), "Not old fm: " + oldFmSt);
		/*
		>>> 算符的变化	and ~> &&, or ~>||,  eq ~>===, ...
		>>> 括号的变化	{ab} ~>${ab},	{..} ~>{=..}
			正则替换可以解决算符和括号。
		>>> 改造 个别eq表达
			{DocEntry} eq null
				~>[undefined, null].includes(${/DocEntry})
		>>> 新增	#ID#	不支持
		>>> 引入includes函数。
			a eq 11, a eq 12 ~>[11,12].inclucdes(a)
		 */
		{//函数正则转换：{DocEntry} eq null ~>[undefined, null].includes(${/DocEntry})
			{// ~>includes:: eg. {/DocEntry} eq null ~>...
				// String f = "\\{/DocEntry\\} (eq|===) null\\}|\\$\\{/DocEntry\\} === null";
				String fromReg = "\\{/DocEntry\\}\\s+(eq|===)\\s+null";
				// String t = "[undefined, null].includes(\\$\\{/DocEntry\\})";
				String toReg = "[undefined, null].includes(\\{/DocEntry\\})";
				String st = oldFmSt.replaceAll(fromReg, toReg);
				oldFmSt = st;
				fromReg = fromReg.replace("/DocEntry", "DocEntry");
				toReg = toReg.replace("/DocEntry", "DocEntry");
				oldFmSt = oldFmSt.replaceAll(fromReg, toReg);
			}
			oldFmSt = oldFmSt.replace("{/DocEntry} eq null", "weilai861462");
		}
		{//算符变化。eg. and~>&&, or ~>..., eq ~>===, ne ~>...
			oldFmSt = B1com.standarlizeExpOp(oldFmSt);
		}
		String ret;
		{//includes function.  eg. c eq b or c eq d ~> to [b,q].includes(c).
			AndOrExp2 exp = AndOrExp2.newInst(-1,oldFmSt);
			Refs.now();
			if (oldAtts != null) {
				B1com.removeSalesOrPurchaseObjType_fromNode(oldAtts, exp.rootNode);
			}
			//({VChangeRdr} !== 'N' && {ObjType} !== '13' && {ObjType} !== '14' && {VDeliveryStatus} !== 'N' || [undefined,null].includes({DocEntry}))
			//({VChangeRdr} !== 'N' && {VDeliveryStatus} !== 'N' || [undefined,null].includes({DocEntry}))
			IncludesFun9.includesFun_transform(exp.rootNode);
			ret = exp.rootNode.getString(1);
		}
		{//变量括号：{abc} ~>${abc}
			if (encloseByLR)//"{="
				ret = closeFormula(ret);
			ret = ret.replaceAll("([\\s\\(=]|^)\\{([^=])", "$1\\$\\{$2");//在（左括|空格|=）花括间、插入$
		}
		if ("asdf".isEmpty()) {
			ret = quoteNum_relatesToObjType(ret);
		}
		return ret;
	}

	public static String closeFormula(String fm) {
		if (fm.matches("true|false")) {
			return fm;
		}
		if (!fm.startsWith("{=")) {
			fm = "{=" + fm + "}";
		}
		return fm;
	}

	public static String andExpToFormular(String fm, String toFm) {
		String ret;
		fm = fm.trim();
		if (toFm == null) {
			toFm = "";
		}
		toFm = toFm.trim();
		Ca.asert(!fm.isEmpty(), "");
		{//remove LR
			if (fm.startsWith("{="))
				fm = fm.substring(2, fm.length() - 1);
			if (toFm.startsWith("{="))
				toFm = toFm.substring(2, toFm.length() - 1);
		}
		{//
			if (fm.equals("false") || toFm.equals("false")) {
				ret = fm;
			} else if (toFm.equals("true") || toFm.isEmpty()) {
				ret = fm;
			} else if (fm.equals("true")) {
				ret = toFm;
			} else {
				if (toFm.contains("||")) {
					if (Str9a.readBracketSt("()", toFm, 0).length() != toFm.length())
						toFm = "(" + toFm + ")";
				}
				ret = fm + " && " + toFm;
			}
			if (ret.matches("true|false")) {
			} else if (!ret.startsWith("{=")) {
				ret = "{=" + ret + "}";
			}
			return ret;
		}
	}


	static int inc;
}
